/*
 * Copyright 2007 Peter Zelenay.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *     
*/
package net.zelenay.jcrviewer.table;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;

/**
 * 
 * @author Peter Zelenay
 *
 */
public class PropertyModel extends AbstractTableModel implements Observer {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private Node activeNode = null;

	private boolean isLoading = false;

	private Executor executor;

	private final List<String[]> propValues = new ArrayList<String[]>();

	public int getColumnCount() {
		return 2;
	}

	public int getRowCount() {
		if (isLoading) {
			return 1;
		}
		if (activeNode == null) {
			return 0;
		}
		return propValues.size();
	}

	public Object getValueAt(int rowIndex, int columnIndex) {
		if (isLoading) {
			return "Loading";
		}
		if (activeNode == null) {
			return "";
		}
		return propValues.get(rowIndex)[columnIndex];
	}

	public void update(Observable o, Object arg) {
		final Node tmpActiveNode = (Node) arg;
		if (!tmpActiveNode.equals(activeNode)) {
			isLoading = true;
			fireTableDataChanged();
			FutureTask<Node> task = new FutureTask<Node>(new Callable<Node>() {
				public Node call() throws Exception {
					// TODO prepare data
					Thread.sleep(1000);
					propValues.clear();
					try {
						PropertyIterator it = tmpActiveNode.getProperties();
						while (it.hasNext()) {
							Property prop = it.nextProperty();
							String[] line = new String[2];
							line[0] = prop.getName();
							if (prop.getDefinition().isMultiple()) {
								Value[] values = prop.getValues();
								StringBuilder sb = new StringBuilder();
								for (Value v : values) {
									sb.append(v.getString()).append(" ,");
								}
								line[1] = sb.toString();
							} else {
								line[1] = prop.getValue().getString();
							}
							propValues.add(line);
						}
					} catch (RepositoryException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					return tmpActiveNode;
				}
			}) {
				@Override
				protected void done() {
					SwingUtilities.invokeLater(new Runnable() {
						public void run() {
							try {
								activeNode = get();
								isLoading = false;
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							} catch (ExecutionException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							fireTableDataChanged();
						}
					});
				}
			};
			getExecutor().execute(task);
		}
	}

	@Override
	public String getColumnName(int column) {
		switch (column) {
		case (0):
			return "Name";
		case (1):
			return "Value";
		}
		return super.getColumnName(column);
	}

	public Executor getExecutor() {
		return executor;
	}

	public void setExecutor(Executor executor) {
		this.executor = executor;
	}

}
